Install and load packages

library(plotly)
library(tidyverse)
library(readr)
library(ggplot2)
library(dplyr)
library(gridExtra)
library(htmlwidgets)

Read CSV files

data <- read.csv("high_elo_opening.csv")

Clean the data file

columns_to_keep <- c(
  "opening_name",
  "side",
  "num_games",
  "ECO",
  "last_played_date",
  "avg_player",
  "perc_draw",
  "perc_white_win",
  "perc_black_win"
)

# Convert the "last_played_date" column to a date format
data$last_played_date <- as.Date(data$last_played_date)

# Create a new dataset with only the relevant columns
cleaned_data <- data %>%
  select(all_of(columns_to_keep))

Exploratory Data Analysis (EDA)

ggplot(cleaned_data, aes(x = avg_player)) +
  geom_histogram(binwidth = 50, fill = "blue", color = "black") +
  labs(title = "Distribution of Average Player Ratings",
       x = "Average Player Rating",
       y = "Frequency")

Analyze Opening Popularity

# Filter for the top 10 most frequently played openings
top_10_openings <- cleaned_data %>%
  group_by(opening_name) %>%
  summarize(total_games = sum(num_games)) %>%
  arrange(desc(total_games)) %>%
  head(10)

# Filter the dataset to include only the top 10 openings
filtered_data <- cleaned_data %>%
  filter(opening_name %in% top_10_openings$opening_name)

# Calculate win rates for white, draw, and black for each opening
opening_win_rates <- filtered_data %>%
  group_by(opening_name) %>%
  summarize(
    perc_white_win = mean(perc_white_win),
    perc_draw = mean(perc_draw),
    perc_black_win = mean(perc_black_win)
  )

# Reshape the data for plotting
opening_win_rates_long <- opening_win_rates %>%
  pivot_longer(
    cols = c(perc_white_win, perc_draw, perc_black_win),
    names_to = "result",
    values_to = "percentage"
  )

# Create the stacked bar chart
ggplot(opening_win_rates_long, aes(x = reorder(opening_name, percentage), y = percentage, fill = result)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  labs(
    title = "Win Rates per Opening (Top 10 Most Popular Openings)",
    x = "Opening",
    y = "Percentage",
    fill = "Result"
  ) +
  theme(legend.position = "bottom")+
  scale_x_discrete(labels = function(x) str_wrap(x, width = 40))

Player Rating Categories

Rating < 2000

# Filter data for player ratings less than 2000
data_below_2000 <- cleaned_data %>%
  filter(avg_player < 2000)

# Identify the top 10 most played openings for ratings below 2000
top_10_openings_below_2000 <- data_below_2000 %>%
  group_by(opening_name) %>%
  summarize(total_games = sum(num_games)) %>%
  arrange(desc(total_games)) %>%
  head(10)

# Calculate win rates for the top 10 openings in this category
win_rates_below_2000 <- data_below_2000 %>%
  filter(opening_name %in% top_10_openings_below_2000$opening_name) %>%
  group_by(opening_name) %>%
  summarize(
    perc_white_win = mean(perc_white_win),
    perc_draw = mean(perc_draw),
    perc_black_win = mean(perc_black_win)
  )

# Reshape the data for plotting
win_rates_below_2000_long <- win_rates_below_2000 %>%
  pivot_longer(
    cols = c(perc_white_win, perc_draw, perc_black_win),
    names_to = "result",
    values_to = "percentage"
  )

# Create a bar chart for player ratings < 2000
ggplot(win_rates_below_2000_long, aes(x = reorder(opening_name, percentage), y = percentage, fill = result)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  labs(
    title = "Win Rates per Opening (Player Ratings < 2000)",
    x = "Opening",
    y = "Percentage",
    fill = "Result"
  ) +
  theme(legend.position = "bottom")+
  scale_x_discrete(labels = function(x) str_wrap(x, width = 40))

Rating 2000-2200

# Filter data for player ratings between 2000 and 2200
data_2000_2200 <- cleaned_data %>%
  filter(avg_player >= 2000, avg_player < 2200)

# Identify the top 10 most played openings for ratings between 2000 and 2200
top_10_openings_2000_2200 <- data_2000_2200 %>%
  group_by(opening_name) %>%
  summarize(total_games = sum(num_games)) %>%
  arrange(desc(total_games)) %>%
  head(10)

# Calculate win rates for the top 10 openings in this category
win_rates_2000_2200 <- data_2000_2200 %>%
  filter(opening_name %in% top_10_openings_2000_2200$opening_name) %>%
  group_by(opening_name) %>%
  summarize(
    perc_white_win = mean(perc_white_win),
    perc_draw = mean(perc_draw),
    perc_black_win = mean(perc_black_win)
  )

# Reshape the data for plotting
win_rates_2000_2200_long <- win_rates_2000_2200 %>%
  pivot_longer(
    cols = c(perc_white_win, perc_draw, perc_black_win),
    names_to = "result",
    values_to = "percentage"
  )

# Create a bar chart for player ratings 2000-2200
ggplot(win_rates_2000_2200_long, aes(x = reorder(opening_name, percentage), y = percentage, fill = result)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  labs(
    title = "Win Rates per Opening (Player Ratings 2000-2200)",
    x = "Opening",
    y = "Percentage",
    fill = "Result"
  ) +
  theme(legend.position = "bottom")+
  scale_x_discrete(labels = function(x) str_wrap(x, width = 40))

Rating 2200+

# Filter data for player ratings 2200+
data_2200_plus <- cleaned_data %>%
  filter(avg_player >= 2200)

# Identify the top 10 most played openings for ratings 2200+
top_10_openings_2200_plus <- data_2200_plus %>%
  group_by(opening_name) %>%
  summarize(total_games = sum(num_games)) %>%
  arrange(desc(total_games)) %>%
  head(10)

# Calculate win rates for the top 10 openings in this category
win_rates_2200_plus <- data_2200_plus %>%
  filter(opening_name %in% top_10_openings_2200_plus$opening_name) %>%
  group_by(opening_name) %>%
  summarize(
    perc_white_win = mean(perc_white_win),
    perc_draw = mean(perc_draw),
    perc_black_win = mean(perc_black_win)
  )

# Reshape the data for plotting
win_rates_2200_plus_long <- win_rates_2200_plus %>%
  pivot_longer(
    cols = c(perc_white_win, perc_draw, perc_black_win),
    names_to = "result",
    values_to = "percentage"
  )

# Create a bar chart for player ratings 2200+
ggplot(win_rates_2200_plus_long, aes(x = reorder(opening_name, percentage), y = percentage, fill = result)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  scale_y_continuous(labels = scales::percent_format(scale = 1)) +
  labs(
    title = "Win Rates per Opening (Player Ratings 2200+)",
    x = "Opening",
    y = "Percentage",
    fill = "Result"
  ) +
  theme(legend.position = "bottom")+
  scale_x_discrete(labels = function(x) str_wrap(x, width = 40))

Interactive Scatterplot

plot_ly(cleaned_data, x = ~avg_player, y = ~num_games, text = ~paste("Opening: ", opening_name, "<br>Win Rate: ", perc_white_win), type = "scatter", mode = "markers", name = "my_plot") %>%
  add_markers(color = ~perc_white_win, colors = "Viridis") %>%
  layout(
    title = "Interactive Opening Popularity vs. Player Ratings",
    xaxis = list(title = "Player Ratings (Average)"),
    yaxis = list(title = "Number of Games Played with Opening"),
    showlegend = FALSE
  )
1600180020002200240005k10k15k20k
203040506070perc_white_winInteractive Opening Popularity vs. Player RatingsPlayer Ratings (Average)Number of Games Played with Openingmy_plot(2168, 6775)Opening: Sicilian Defense, Four Knights Variation Win Rate: 37.9
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKSW5zdGFsbCBhbmQgbG9hZCBwYWNrYWdlcwpgYGB7cn0KbGlicmFyeShwbG90bHkpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGh0bWx3aWRnZXRzKQpgYGAKClJlYWQgQ1NWIGZpbGVzCmBgYHtyfQpkYXRhIDwtIHJlYWQuY3N2KCJoaWdoX2Vsb19vcGVuaW5nLmNzdiIpCmBgYAoKQ2xlYW4gdGhlIGRhdGEgZmlsZQpgYGB7cn0KY29sdW1uc190b19rZWVwIDwtIGMoCiAgIm9wZW5pbmdfbmFtZSIsCiAgInNpZGUiLAogICJudW1fZ2FtZXMiLAogICJFQ08iLAogICJsYXN0X3BsYXllZF9kYXRlIiwKICAiYXZnX3BsYXllciIsCiAgInBlcmNfZHJhdyIsCiAgInBlcmNfd2hpdGVfd2luIiwKICAicGVyY19ibGFja193aW4iCikKCiMgQ29udmVydCB0aGUgImxhc3RfcGxheWVkX2RhdGUiIGNvbHVtbiB0byBhIGRhdGUgZm9ybWF0CmRhdGEkbGFzdF9wbGF5ZWRfZGF0ZSA8LSBhcy5EYXRlKGRhdGEkbGFzdF9wbGF5ZWRfZGF0ZSkKCiMgQ3JlYXRlIGEgbmV3IGRhdGFzZXQgd2l0aCBvbmx5IHRoZSByZWxldmFudCBjb2x1bW5zCmNsZWFuZWRfZGF0YSA8LSBkYXRhICU+JQogIHNlbGVjdChhbGxfb2YoY29sdW1uc190b19rZWVwKSkKYGBgCgojIEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgKEVEQSkKYGBge3J9CmdncGxvdChjbGVhbmVkX2RhdGEsIGFlcyh4ID0gYXZnX3BsYXllcikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUwLCBmaWxsID0gImJsdWUiLCBjb2xvciA9ICJibGFjayIpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBBdmVyYWdlIFBsYXllciBSYXRpbmdzIiwKICAgICAgIHggPSAiQXZlcmFnZSBQbGF5ZXIgUmF0aW5nIiwKICAgICAgIHkgPSAiRnJlcXVlbmN5IikKYGBgCgojIyBBbmFseXplIE9wZW5pbmcgUG9wdWxhcml0eQpgYGB7cn0KIyBGaWx0ZXIgZm9yIHRoZSB0b3AgMTAgbW9zdCBmcmVxdWVudGx5IHBsYXllZCBvcGVuaW5ncwp0b3BfMTBfb3BlbmluZ3MgPC0gY2xlYW5lZF9kYXRhICU+JQogIGdyb3VwX2J5KG9wZW5pbmdfbmFtZSkgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2dhbWVzID0gc3VtKG51bV9nYW1lcykpICU+JQogIGFycmFuZ2UoZGVzYyh0b3RhbF9nYW1lcykpICU+JQogIGhlYWQoMTApCgojIEZpbHRlciB0aGUgZGF0YXNldCB0byBpbmNsdWRlIG9ubHkgdGhlIHRvcCAxMCBvcGVuaW5ncwpmaWx0ZXJlZF9kYXRhIDwtIGNsZWFuZWRfZGF0YSAlPiUKICBmaWx0ZXIob3BlbmluZ19uYW1lICVpbiUgdG9wXzEwX29wZW5pbmdzJG9wZW5pbmdfbmFtZSkKCiMgQ2FsY3VsYXRlIHdpbiByYXRlcyBmb3Igd2hpdGUsIGRyYXcsIGFuZCBibGFjayBmb3IgZWFjaCBvcGVuaW5nCm9wZW5pbmdfd2luX3JhdGVzIDwtIGZpbHRlcmVkX2RhdGEgJT4lCiAgZ3JvdXBfYnkob3BlbmluZ19uYW1lKSAlPiUKICBzdW1tYXJpemUoCiAgICBwZXJjX3doaXRlX3dpbiA9IG1lYW4ocGVyY193aGl0ZV93aW4pLAogICAgcGVyY19kcmF3ID0gbWVhbihwZXJjX2RyYXcpLAogICAgcGVyY19ibGFja193aW4gPSBtZWFuKHBlcmNfYmxhY2tfd2luKQogICkKCiMgUmVzaGFwZSB0aGUgZGF0YSBmb3IgcGxvdHRpbmcKb3BlbmluZ193aW5fcmF0ZXNfbG9uZyA8LSBvcGVuaW5nX3dpbl9yYXRlcyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gYyhwZXJjX3doaXRlX3dpbiwgcGVyY19kcmF3LCBwZXJjX2JsYWNrX3dpbiksCiAgICBuYW1lc190byA9ICJyZXN1bHQiLAogICAgdmFsdWVzX3RvID0gInBlcmNlbnRhZ2UiCiAgKQoKIyBDcmVhdGUgdGhlIHN0YWNrZWQgYmFyIGNoYXJ0CmdncGxvdChvcGVuaW5nX3dpbl9yYXRlc19sb25nLCBhZXMoeCA9IHJlb3JkZXIob3BlbmluZ19uYW1lLCBwZXJjZW50YWdlKSwgeSA9IHBlcmNlbnRhZ2UsIGZpbGwgPSByZXN1bHQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KHNjYWxlID0gMSkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiV2luIFJhdGVzIHBlciBPcGVuaW5nIChUb3AgMTAgTW9zdCBQb3B1bGFyIE9wZW5pbmdzKSIsCiAgICB4ID0gIk9wZW5pbmciLAogICAgeSA9ICJQZXJjZW50YWdlIiwKICAgIGZpbGwgPSAiUmVzdWx0IgogICkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gNDApKQpgYGAKCiMjIFBsYXllciBSYXRpbmcgQ2F0ZWdvcmllcwojIyMgUmF0aW5nIDwgMjAwMApgYGB7cn0KIyBGaWx0ZXIgZGF0YSBmb3IgcGxheWVyIHJhdGluZ3MgbGVzcyB0aGFuIDIwMDAKZGF0YV9iZWxvd18yMDAwIDwtIGNsZWFuZWRfZGF0YSAlPiUKICBmaWx0ZXIoYXZnX3BsYXllciA8IDIwMDApCgojIElkZW50aWZ5IHRoZSB0b3AgMTAgbW9zdCBwbGF5ZWQgb3BlbmluZ3MgZm9yIHJhdGluZ3MgYmVsb3cgMjAwMAp0b3BfMTBfb3BlbmluZ3NfYmVsb3dfMjAwMCA8LSBkYXRhX2JlbG93XzIwMDAgJT4lCiAgZ3JvdXBfYnkob3BlbmluZ19uYW1lKSAlPiUKICBzdW1tYXJpemUodG90YWxfZ2FtZXMgPSBzdW0obnVtX2dhbWVzKSkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2dhbWVzKSkgJT4lCiAgaGVhZCgxMCkKCiMgQ2FsY3VsYXRlIHdpbiByYXRlcyBmb3IgdGhlIHRvcCAxMCBvcGVuaW5ncyBpbiB0aGlzIGNhdGVnb3J5Cndpbl9yYXRlc19iZWxvd18yMDAwIDwtIGRhdGFfYmVsb3dfMjAwMCAlPiUKICBmaWx0ZXIob3BlbmluZ19uYW1lICVpbiUgdG9wXzEwX29wZW5pbmdzX2JlbG93XzIwMDAkb3BlbmluZ19uYW1lKSAlPiUKICBncm91cF9ieShvcGVuaW5nX25hbWUpICU+JQogIHN1bW1hcml6ZSgKICAgIHBlcmNfd2hpdGVfd2luID0gbWVhbihwZXJjX3doaXRlX3dpbiksCiAgICBwZXJjX2RyYXcgPSBtZWFuKHBlcmNfZHJhdyksCiAgICBwZXJjX2JsYWNrX3dpbiA9IG1lYW4ocGVyY19ibGFja193aW4pCiAgKQoKIyBSZXNoYXBlIHRoZSBkYXRhIGZvciBwbG90dGluZwp3aW5fcmF0ZXNfYmVsb3dfMjAwMF9sb25nIDwtIHdpbl9yYXRlc19iZWxvd18yMDAwICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBjKHBlcmNfd2hpdGVfd2luLCBwZXJjX2RyYXcsIHBlcmNfYmxhY2tfd2luKSwKICAgIG5hbWVzX3RvID0gInJlc3VsdCIsCiAgICB2YWx1ZXNfdG8gPSAicGVyY2VudGFnZSIKICApCgojIENyZWF0ZSBhIGJhciBjaGFydCBmb3IgcGxheWVyIHJhdGluZ3MgPCAyMDAwCmdncGxvdCh3aW5fcmF0ZXNfYmVsb3dfMjAwMF9sb25nLCBhZXMoeCA9IHJlb3JkZXIob3BlbmluZ19uYW1lLCBwZXJjZW50YWdlKSwgeSA9IHBlcmNlbnRhZ2UsIGZpbGwgPSByZXN1bHQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KHNjYWxlID0gMSkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiV2luIFJhdGVzIHBlciBPcGVuaW5nIChQbGF5ZXIgUmF0aW5ncyA8IDIwMDApIiwKICAgIHggPSAiT3BlbmluZyIsCiAgICB5ID0gIlBlcmNlbnRhZ2UiLAogICAgZmlsbCA9ICJSZXN1bHQiCiAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyX3dyYXAoeCwgd2lkdGggPSA0MCkpCmBgYAoKIyMjIFJhdGluZyAyMDAwLTIyMDAKYGBge3J9CiMgRmlsdGVyIGRhdGEgZm9yIHBsYXllciByYXRpbmdzIGJldHdlZW4gMjAwMCBhbmQgMjIwMApkYXRhXzIwMDBfMjIwMCA8LSBjbGVhbmVkX2RhdGEgJT4lCiAgZmlsdGVyKGF2Z19wbGF5ZXIgPj0gMjAwMCwgYXZnX3BsYXllciA8IDIyMDApCgojIElkZW50aWZ5IHRoZSB0b3AgMTAgbW9zdCBwbGF5ZWQgb3BlbmluZ3MgZm9yIHJhdGluZ3MgYmV0d2VlbiAyMDAwIGFuZCAyMjAwCnRvcF8xMF9vcGVuaW5nc18yMDAwXzIyMDAgPC0gZGF0YV8yMDAwXzIyMDAgJT4lCiAgZ3JvdXBfYnkob3BlbmluZ19uYW1lKSAlPiUKICBzdW1tYXJpemUodG90YWxfZ2FtZXMgPSBzdW0obnVtX2dhbWVzKSkgJT4lCiAgYXJyYW5nZShkZXNjKHRvdGFsX2dhbWVzKSkgJT4lCiAgaGVhZCgxMCkKCiMgQ2FsY3VsYXRlIHdpbiByYXRlcyBmb3IgdGhlIHRvcCAxMCBvcGVuaW5ncyBpbiB0aGlzIGNhdGVnb3J5Cndpbl9yYXRlc18yMDAwXzIyMDAgPC0gZGF0YV8yMDAwXzIyMDAgJT4lCiAgZmlsdGVyKG9wZW5pbmdfbmFtZSAlaW4lIHRvcF8xMF9vcGVuaW5nc18yMDAwXzIyMDAkb3BlbmluZ19uYW1lKSAlPiUKICBncm91cF9ieShvcGVuaW5nX25hbWUpICU+JQogIHN1bW1hcml6ZSgKICAgIHBlcmNfd2hpdGVfd2luID0gbWVhbihwZXJjX3doaXRlX3dpbiksCiAgICBwZXJjX2RyYXcgPSBtZWFuKHBlcmNfZHJhdyksCiAgICBwZXJjX2JsYWNrX3dpbiA9IG1lYW4ocGVyY19ibGFja193aW4pCiAgKQoKIyBSZXNoYXBlIHRoZSBkYXRhIGZvciBwbG90dGluZwp3aW5fcmF0ZXNfMjAwMF8yMjAwX2xvbmcgPC0gd2luX3JhdGVzXzIwMDBfMjIwMCAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gYyhwZXJjX3doaXRlX3dpbiwgcGVyY19kcmF3LCBwZXJjX2JsYWNrX3dpbiksCiAgICBuYW1lc190byA9ICJyZXN1bHQiLAogICAgdmFsdWVzX3RvID0gInBlcmNlbnRhZ2UiCiAgKQoKIyBDcmVhdGUgYSBiYXIgY2hhcnQgZm9yIHBsYXllciByYXRpbmdzIDIwMDAtMjIwMApnZ3Bsb3Qod2luX3JhdGVzXzIwMDBfMjIwMF9sb25nLCBhZXMoeCA9IHJlb3JkZXIob3BlbmluZ19uYW1lLCBwZXJjZW50YWdlKSwgeSA9IHBlcmNlbnRhZ2UsIGZpbGwgPSByZXN1bHQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KHNjYWxlID0gMSkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiV2luIFJhdGVzIHBlciBPcGVuaW5nIChQbGF5ZXIgUmF0aW5ncyAyMDAwLTIyMDApIiwKICAgIHggPSAiT3BlbmluZyIsCiAgICB5ID0gIlBlcmNlbnRhZ2UiLAogICAgZmlsbCA9ICJSZXN1bHQiCiAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyX3dyYXAoeCwgd2lkdGggPSA0MCkpCmBgYAoKIyMjIFJhdGluZyAyMjAwKwpgYGB7cn0KIyBGaWx0ZXIgZGF0YSBmb3IgcGxheWVyIHJhdGluZ3MgMjIwMCsKZGF0YV8yMjAwX3BsdXMgPC0gY2xlYW5lZF9kYXRhICU+JQogIGZpbHRlcihhdmdfcGxheWVyID49IDIyMDApCgojIElkZW50aWZ5IHRoZSB0b3AgMTAgbW9zdCBwbGF5ZWQgb3BlbmluZ3MgZm9yIHJhdGluZ3MgMjIwMCsKdG9wXzEwX29wZW5pbmdzXzIyMDBfcGx1cyA8LSBkYXRhXzIyMDBfcGx1cyAlPiUKICBncm91cF9ieShvcGVuaW5nX25hbWUpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9nYW1lcyA9IHN1bShudW1fZ2FtZXMpKSAlPiUKICBhcnJhbmdlKGRlc2ModG90YWxfZ2FtZXMpKSAlPiUKICBoZWFkKDEwKQoKIyBDYWxjdWxhdGUgd2luIHJhdGVzIGZvciB0aGUgdG9wIDEwIG9wZW5pbmdzIGluIHRoaXMgY2F0ZWdvcnkKd2luX3JhdGVzXzIyMDBfcGx1cyA8LSBkYXRhXzIyMDBfcGx1cyAlPiUKICBmaWx0ZXIob3BlbmluZ19uYW1lICVpbiUgdG9wXzEwX29wZW5pbmdzXzIyMDBfcGx1cyRvcGVuaW5nX25hbWUpICU+JQogIGdyb3VwX2J5KG9wZW5pbmdfbmFtZSkgJT4lCiAgc3VtbWFyaXplKAogICAgcGVyY193aGl0ZV93aW4gPSBtZWFuKHBlcmNfd2hpdGVfd2luKSwKICAgIHBlcmNfZHJhdyA9IG1lYW4ocGVyY19kcmF3KSwKICAgIHBlcmNfYmxhY2tfd2luID0gbWVhbihwZXJjX2JsYWNrX3dpbikKICApCgojIFJlc2hhcGUgdGhlIGRhdGEgZm9yIHBsb3R0aW5nCndpbl9yYXRlc18yMjAwX3BsdXNfbG9uZyA8LSB3aW5fcmF0ZXNfMjIwMF9wbHVzICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBjKHBlcmNfd2hpdGVfd2luLCBwZXJjX2RyYXcsIHBlcmNfYmxhY2tfd2luKSwKICAgIG5hbWVzX3RvID0gInJlc3VsdCIsCiAgICB2YWx1ZXNfdG8gPSAicGVyY2VudGFnZSIKICApCgojIENyZWF0ZSBhIGJhciBjaGFydCBmb3IgcGxheWVyIHJhdGluZ3MgMjIwMCsKZ2dwbG90KHdpbl9yYXRlc18yMjAwX3BsdXNfbG9uZywgYWVzKHggPSByZW9yZGVyKG9wZW5pbmdfbmFtZSwgcGVyY2VudGFnZSksIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gcmVzdWx0KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChzY2FsZSA9IDEpKSArCiAgbGFicygKICAgIHRpdGxlID0gIldpbiBSYXRlcyBwZXIgT3BlbmluZyAoUGxheWVyIFJhdGluZ3MgMjIwMCspIiwKICAgIHggPSAiT3BlbmluZyIsCiAgICB5ID0gIlBlcmNlbnRhZ2UiLAogICAgZmlsbCA9ICJSZXN1bHQiCiAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyX3dyYXAoeCwgd2lkdGggPSA0MCkpCmBgYAoKIyMgSW50ZXJhY3RpdmUgU2NhdHRlcnBsb3QKYGBge3IsIGZpZy53aWR0aCA9IDEwfQpwbG90X2x5KGNsZWFuZWRfZGF0YSwgeCA9IH5hdmdfcGxheWVyLCB5ID0gfm51bV9nYW1lcywgdGV4dCA9IH5wYXN0ZSgiT3BlbmluZzogIiwgb3BlbmluZ19uYW1lLCAiPGJyPldpbiBSYXRlOiAiLCBwZXJjX3doaXRlX3dpbiksIHR5cGUgPSAic2NhdHRlciIsIG1vZGUgPSAibWFya2VycyIsIG5hbWUgPSAibXlfcGxvdCIpICU+JQogIGFkZF9tYXJrZXJzKGNvbG9yID0gfnBlcmNfd2hpdGVfd2luLCBjb2xvcnMgPSAiVmlyaWRpcyIpICU+JQogIGxheW91dCgKICAgIHRpdGxlID0gIkludGVyYWN0aXZlIE9wZW5pbmcgUG9wdWxhcml0eSB2cy4gUGxheWVyIFJhdGluZ3MiLAogICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlBsYXllciBSYXRpbmdzIChBdmVyYWdlKSIpLAogICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIk51bWJlciBvZiBHYW1lcyBQbGF5ZWQgd2l0aCBPcGVuaW5nIiksCiAgICBzaG93bGVnZW5kID0gRkFMU0UKICApCmBgYA==